package marioarena.tcpconnection;
import marioarena.ConnectionHandler;
import marioarena.Constants;
import marioarena.client.Client;
import marioarena.game.Bullet;


/**
 * A threaded bullet processor, which processes projectile data received 
 * using TCP in a new thread. This prevents any delays when processing 
 * a large amount of projectiles.
 */
public class ThreadedBulletProcessor extends Thread {
	private String[] splitData;
	private Client client;
	
	/**
	 * Constructs a new threaded bullet processor, which processes the projectile 
	 * data received using TCP in a new thread. This prevents any delays when processing 
	 * a large amount of projectiles.
	 * @param splitTcpData The split TCP data to process.
	 * @param client The owner of this projectile.
	 */
	public ThreadedBulletProcessor(String[] splitTcpData, Client client)
	{
		this.splitData = splitTcpData;
		this.client = client;
	}
	
	public void run()
	{
		try{
			String bulletType = splitData[1];
			int spawnX = Integer.parseInt(splitData[2]);
			int spawnY = Integer.parseInt(splitData[3]);
			float directionX = Float.parseFloat(replaceCommaByDot(splitData[4]));
			float directionY = Float.parseFloat(replaceCommaByDot(splitData[5]));
			int speed = Integer.parseInt(splitData[6]);

			if (bulletType.equals("10"))
			{
				// Create a bullet and add it to the player's bullet list. This may happen concurrently with 
				// other threads, so we need to lock the list before adding.
				Bullet newBullet = new Bullet(bulletType, spawnX, spawnY, directionX, directionY, speed);
				synchronized (this.client.getPlayerData().getBullets())
				{
					this.client.getPlayerData().addBullet(newBullet);
				}
				
				String pingAdaptedSpawnX = String.valueOf((int)newBullet.getPingAdaptedSpawnPositionX(this.client));
				String pingAdaptedSpawnY = String.valueOf((int)newBullet.getPingAdaptedSpawnPositionY(this.client));
				ConnectionHandler.getInstance().sendToAllClients("21_" + newBullet.getId() + "_" + newBullet.getType() + "_" 
						+ pingAdaptedSpawnX + "_" + pingAdaptedSpawnY + "_" + splitData[4] + "_" + splitData[5]);
			}
			else if (bulletType.equals("11"))
			{
				final int nrOfProjectiles = Constants.specialProjectileAmount;
				String offsetDegrees = Constants.specialProjectileDegrees + ""; // 10 degrees offset between projectiles
				String bulletTcpString = "22_";
				
				double midProjectileRotation = Math.atan2(directionY, directionX);
                int dir = -1; // direction respective to the mid projectile; top or bottom
                int counter = 1;
				for (int i = 0; i < nrOfProjectiles; i++) // Create 3 projectiles
				{
					Bullet newBullet;
					if (i == 0)
					{
						// The first projectile goes straight
						newBullet = new Bullet(bulletType, spawnX, spawnY, directionX, directionY, speed);
					}
					else // All other projectiles have an offset in degrees
					{
						// Calculate the bullet's direction, taking the offset in degrees into account
						// Create a projectile with an offset
	                    double projectileRotation = midProjectileRotation + Math.toRadians((counter * 10) * dir);
	                    double projectileDirectionX = Math.cos(projectileRotation);
	                    double projectileDirectionY = Math.sin(projectileRotation);
	                    double vectorLength = Math.sqrt((projectileDirectionX * projectileDirectionX) + (projectileDirectionY * projectileDirectionY));
	                    float normalizedDirX = (float)(projectileDirectionX / vectorLength);
	                    float normalizedDirY = (float)(projectileDirectionY / vectorLength);
	                    
	                    if (dir == 1)
	                        counter++; // A projectile has been added both to the top and to the bottom
	                    dir *= -1; // Switch direction
						
						
						// Create the bullet
						newBullet = new Bullet(bulletType, spawnX, spawnY, normalizedDirX, normalizedDirY, speed);
					}
					
					synchronized (this.client.getPlayerData().getBullets())
					{
						this.client.getPlayerData().addBullet(newBullet);
					}
					
					String id = String.valueOf(newBullet.getId());
					
					bulletTcpString += id;
					if (i < nrOfProjectiles - 1)
						bulletTcpString += "#";

					// Cannot use ping adapted spawn position because we send only one spawn position
				}
				
															// spawnX			 spawnY				   directionX			directionY
				bulletTcpString += ("_" + bulletType + "_" + splitData[2] + "_" + splitData[3] + "_" + splitData[4] + "_" + splitData[5] + "_" + offsetDegrees);
				ConnectionHandler.getInstance().sendToAllClients(bulletTcpString);
			}
		}
		catch(Exception e){
			System.out.println("Could not create bullet: " + e);
		}
	}
	
	private String replaceCommaByDot(String stringToCheck){
		String result = stringToCheck;
		result = result.replace(',', '.');
		return result;
	}
}
